/*
 * testEntidades.cpp
 *
 *  Created on: 09/08/2014
 *      Author: migue
 */


#include "../comun/SalaRemota.h"
#include "../comun/ParqueRemoto.h"
#include "../comun/ServidorRemoto.h"
#include "../ipcRemoto/SemaforoRemoto.h"


#include <iostream>
#include <vector>

using namespace std;

void salirPorError(SemaforoRemoto& sem) {
	sem.cerrarConexion();

	MENSAJE* msj = NULL;

	msj->id = msj->id + +1;

	exit(1);
}

int main(int argc, char** argv) {

	int errores = 0;

	ServidorRemoto serv;


	int idCliente = serv.pedirIdAdministrador();
	int idBroker = serv.idBrokerConectado();

	ParqueRemoto parque(idCliente, idBroker);
	SemaforoRemoto semParque(ID_MUTEX_PARQUE, idCliente, idBroker);

	semParque.iniciarConexion();


	semParque.wait();
	parque.inicializar();
	parque.abrirParque();
	semParque.signal();

	if(parque.parqueAbierto() == false) {
		cout << "Error Parque no se pudo abrir " << endl;
		errores++;
	}
	else {
		cout << "[OK] Parque se abrio correctamente" << endl;
	}


	semParque.wait();
	if (parque.hayPersonasDentro() == true  && parque.personasDentro() != 0) {
		cout << "Error todavia no hay persona dento del parque " << endl;
		errores ++;
	}
	else {
		cout << " [OK] Parque aun vacio" << endl;
	}
	semParque.signal();



	parque.registrarIngreso();
	parque.registrarIngreso();
	parque.registrarIngreso();

	if (parque.personasDentro() != 3) {
		cout << "Error Personas dentro del parque incorrectas" << endl;
		errores++;
	}
	else {
		cout << "[OK] Personas que ingresaron bien " << endl;
	}

	parque.registrarIngreso();

	parque.registrarSalida(0);
	parque.registrarSalida(1);

	if (parque.personasDentro() != 2) {
		cout << "Error Personas dentro del parque incorrectas" << endl;
		errores++;
	}
	else {
		cout << "[OK] Personas que ingresaron bien " << endl;
	}



	parque.agregarBusesDeRepuesto(20);

	if (parque.busesDeRepuesto() != CANT_BUSES_REPUESTO + 20) {
		cout << "Error en la cantidad de buses de repuesto" << endl;
		errores++;
	}
	else {
		cout << "[OK] cantidad de buses de repuesto correcta" << endl;
	}

	parque.repuestoDeBUSUsado();
	parque.repuestoDeBUSUsado();
	parque.repuestoDeBUSUsado();


	if (parque.busesDeRepuesto() != CANT_BUSES_REPUESTO + 17) {
		cout << "Error en la cantidad de buses de repuesto usados" << endl;
		errores++;
	}
	else {
		cout << "[OK] cantidad de buses de repuesto correcta usados" << endl;
	}

	parque.registrarIngreso();
	parque.registrarIngreso();
	parque.registrarIngreso();


	parque.registrarSalida(1);
	parque.registrarSalida(2);
	parque.registrarSalida(3);
	parque.registrarSalida(4);
	parque.registrarSalida(5);


	if (parque.personasDentro() != 0 && parque.hayPersonasDentro() != false) {
		cout << "Error no hay personas dentro pero indica que si." << endl;
		salirPorError(semParque);
	}
	else {
		cout << "[OK] Personas egresadas correctamente" << endl;
	}

	parque.cerrarParque();

	if (parque.parqueAbierto() == true) {
		cout << "Error parque cerrado pero indica abierto" << endl;
		salirPorError(semParque);
	}
	else {
		cout << "[OK] Parque cerrado correctamente"<< endl;
	}



	/*******************************************************************************************/


	vector<int> ids;

	int numSala;
	int proxId;
	// pruebos las Salas de Entrada
	for (int i = 0; i < CANT_ENTRADAS ;++i) {
		numSala = i + 1;
		ids.clear();

		cout << "++Pruebas para Sala de Entrada " << i << endl;

		SalaRemota sala(numSala, Tipos::LUGAR_ENTRADA, idCliente, idBroker);
		SemaforoRemoto semSala(ID_MUTEX_SALA_ENT(numSala), idCliente, idBroker);
		SemaforoRemoto semLleno(ID_SEM_SALA_ENT_LLENO(numSala), idCliente, idBroker);



		if (sala.cantidadDePersonas() != 0) {
			cout << "Error cantidad de personas, deberia haber 0 pero es: " << sala.cantidadDePersonas() << endl;
			salirPorError(semParque);
		}

		if (sala.hayPersonas() == true) {
			cout << "Error No hay personas en sala, aunque se indica que si" << endl;
			salirPorError(semParque);
		}

		if (sala.salaLlena() == true) {
			cout << "Error indica que la sala esta llena pero no es asi" << endl;
			salirPorError(semParque);
		}



		for (int j = 0; j < CANTMAX ; ++j) {
			semSala.wait();
			ids.push_back(j*100 + j*3 + j + 1);
			sala.reservarLugar(ids[j]);

			sala.colocarEnReserva(ids[j]);

			semSala.signal();
		}

		cout << "\t - ingresadas " << CANTMAX <<" personas" << endl;

		if (sala.cantidadDePersonas() != CANTMAX) {
			cout << "Error cantidad de personas en sala es 0, aunque no hay lugar" << endl;
			salirPorError(semParque);
		}

		if (sala.hayPersonas() == false) {
			cout << "Error No hay personas en sala, aunque se indica que si" << endl;
			salirPorError(semParque);
		}

		if (sala.salaLlena() == false) {
			cout << "Error indica que la sala esta llena pero no es asi" << endl;
			salirPorError(semParque);
		}

		for (int j = 0 ; j < CANTMAX ; ++j) {

			proxId = sala.verProximaPersona();

			if (ids[j] != proxId) {
				cout << "Se esperaba sacar id: " << ids[j];
				cout << ", pero el proximo id es:" << proxId << endl;
				salirPorError(semParque);
			}

			sala.sacarPersona(ids[j]);
		}

		cout << "\t - sacadas " << CANTMAX <<" personas" << endl;

		if (sala.cantidadDePersonas() != 0) {
			cout << "Error cantidad de personas en sala es distinta de 0, debiendo ser 0, ya que se vacio la sala" << endl;
			salirPorError(semParque);
		}

		if (sala.hayPersonas() == true) {
			cout << "Error No hay personas en sala, aunque se indica que si, ya que se vacio" << endl;
			salirPorError(semParque);
		}

		if (sala.salaLlena() == true) {
			cout << "Error indica que la sala esta llena pero no es asi, ya que se vacio" << endl;
			salirPorError(semParque);
		}


		cout << "\t - prueba finalizada" << endl;

	}


	///////////////////////////////////////////////////////////////////

	// pruebos las Salas de Zoo
	for (int i = 0; i < CANT_ENTRADAS ;++i) {
		ids.clear();
		numSala = i + 1;

		cout << "+++Pruebas para Sala de Zoo " << i << endl;

		SalaRemota sala(numSala, Tipos::LUGAR_ZOO, idCliente, idBroker);
		SemaforoRemoto semSala(ID_MUTEX_SALA_ZOO(numSala), idCliente, idBroker);
		SemaforoRemoto semLleno(ID_SEM_SALA_ZOO_LLENO(numSala), idCliente, idBroker);



		if (sala.cantidadDePersonas() != 0) {
			cout << "Error cantidad de personas, deberia haber 0 y es: " << sala.cantidadDePersonas() << endl;
			salirPorError(semParque);
		}

		if (sala.hayPersonas() == true) {
			cout << "Error No hay personas en sala, aunque se indica que si" << endl;
			salirPorError(semParque);
		}

		if (sala.salaLlena() == true) {
			cout << "Error indica que la sala esta llena pero no es asi" << endl;
			salirPorError(semParque);
		}



		for (int j = 0; j < CANTMAX ; ++j) {
			semSala.wait();
			ids.push_back(j*100 + j*3 + j + 2);
			sala.reservarLugar(ids[j]);

			sala.colocarEnReserva(ids[j]);

			semSala.signal();
		}

		cout << "\t - colocadas " << CANTMAX <<" personas" << endl;

		if (sala.cantidadDePersonas() != CANTMAX) {
			cout << "Error cantidad de personas en sala es 0, aunque no hay lugar" << endl;
			salirPorError(semParque);
		}

		if (sala.hayPersonas() == false) {
			cout << "Error No hay personas en sala, aunque se indica que si" << endl;
			salirPorError(semParque);
		}

		if (sala.salaLlena() == false) {
			cout << "Error indica que la sala esta llena pero no es asi" << endl;
			salirPorError(semParque);
		}

		for (int j = 0 ; j < CANTMAX ; ++j) {

			proxId = sala.verProximaPersona();

			if (ids[j] != proxId) {
				cout << "Se esperaba sacar id: " << ids[j];
				cout << ", pero el proximo id es:" << proxId << endl;
				salirPorError(semParque);
			}

			sala.sacarPersona(ids[j]);
		}

		cout << "\t - sacadas " << CANTMAX <<" personas" << endl;

		if (sala.cantidadDePersonas() != 0) {
			cout << "Error cantidad de personas en sala es  distinta de 0, debiendo ser 0, ya que se vacio la sala" << endl;
			salirPorError(semParque);
		}

		if (sala.hayPersonas() == true) {
			cout << "Error No hay personas en sala, aunque se indica que si, ya que se vacio" << endl;
			salirPorError(semParque);
		}

		if (sala.salaLlena() == true) {
			cout << "Error indica que la sala esta llena pero no es asi, ya que se vacio" << endl;
			salirPorError(semParque);
		}


		cout << "\t - prueba finalizada" << endl;
	}


	cout << "[OK] Test Finalizado Sin errores." << endl;

	semParque.cerrarConexion();

	return 0;
}

